package com.boby.lib_common.extens

import android.animation.ObjectAnimator
import android.animation.ValueAnimator
import android.app.Activity
import android.app.Dialog
import android.content.ClipData
import android.content.ClipboardManager
import android.content.Context
import android.content.Intent
import android.content.res.Resources
import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Outline
import android.graphics.drawable.ColorDrawable
import android.net.ConnectivityManager
import android.net.Uri
import android.os.Build
import android.os.Environment
import android.os.Handler
import android.os.IBinder
import android.os.Looper
import android.provider.MediaStore
import android.util.DisplayMetrics
import android.util.Log
import android.util.TypedValue
import android.view.Gravity
import android.view.View
import android.view.ViewOutlineProvider
import android.view.Window
import android.view.WindowManager
import android.view.inputmethod.InputMethodManager
import android.widget.EditText
import android.widget.TextView
import android.widget.Toast
import androidx.annotation.LayoutRes
import androidx.annotation.StringRes
import androidx.annotation.StyleRes
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.LinearSmoothScroller
import androidx.recyclerview.widget.RecyclerView
import com.hjq.toast.ToastUtils

import java.io.ByteArrayOutputStream
import java.io.File
import java.io.FileNotFoundException
import java.io.FileOutputStream
import java.io.IOException
import java.math.BigDecimal
import java.util.concurrent.TimeUnit
import java.util.regex.Pattern


fun toast(message: CharSequence?, duration: Int = Toast.LENGTH_SHORT) {
    if (message.isNullOrBlank()) return
//    Toast.makeText(BaseApplication.instance(), msg, Toast.LENGTH_SHORT).show()
    ToastUtils.show(message)
}

/**创建一个自定义dialog*/
fun Context.newDialog(
        @LayoutRes layoutRes: Int,
        dialog: Dialog.() -> Unit,
        build: (DialogBuild.() -> Unit)? = null
): Dialog =
        if (build == null) {
            DialogBuild(layoutRes, this, dialog).build()
        } else {
            DialogBuild(layoutRes, this, dialog).apply(build).build()
        }

class DialogBuild(
        @LayoutRes private val layoutRes: Int,
        private val context: Context,
        private val mDialog: Dialog.() -> Unit
) {
    var gravity = Gravity.NO_GRAVITY
    var width = WindowManager.LayoutParams.WRAP_CONTENT
    var height = WindowManager.LayoutParams.WRAP_CONTENT
    var cancelable = true

    @StyleRes
    var style = 0

    @StyleRes
    var theme = 0

    internal fun build(): Dialog {
        val dialog = if (theme == 0) Dialog(context) else Dialog(context, theme)
        dialog.requestWindowFeature(Window.FEATURE_NO_TITLE)
        dialog.setContentView(layoutRes)
        val window = dialog.window
        window?.setBackgroundDrawable(ColorDrawable(0))
        val params = window?.attributes
        params?.width = width
        params?.height = height
        params?.gravity = gravity
        window?.attributes = params
        if (style != 0) {
            window?.attributes?.windowAnimations = style
        }
        dialog.apply(mDialog)
        dialog?.setCanceledOnTouchOutside(cancelable)
        dialog?.setCancelable(cancelable)
        return dialog
    }
}

/**创建一个自定义dialog*/
fun <T> Context.newCustomDialog(
        @LayoutRes layoutRes: Int,
        dialog: CustomDialog<T>.() -> Unit,
        build: (CustomDialogBuild<T>.() -> Unit)? = null
): CustomDialog<T> =
        if (build == null) {
            CustomDialogBuild(layoutRes, this, dialog).build()
        } else {
            CustomDialogBuild(layoutRes, this, dialog).apply(build).build()
        }

class CustomDialog<T : Any?>(context: Context) : Dialog(context) {
    var onShow: ((t: T?) -> Unit)? = null
    fun show(t: T?) {
        show()
        onShow?.invoke(t)
    }
}

class CustomDialogBuild<T>(
        @LayoutRes private val layoutRes: Int,
        private val context: Context,
        private val mDialog: CustomDialog<T>.() -> Unit
) {
    var gravity = Gravity.NO_GRAVITY
    var width = WindowManager.LayoutParams.WRAP_CONTENT
    var height = WindowManager.LayoutParams.WRAP_CONTENT

    @StyleRes
    var style = 0

    internal fun build(): CustomDialog<T> {
        val dialog = CustomDialog<T>(context)
        dialog.requestWindowFeature(Window.FEATURE_NO_TITLE)
        dialog.setContentView(layoutRes)
        val window = dialog.window
        window?.setBackgroundDrawable(ColorDrawable(0))
        val params = window?.attributes
        params?.width = width
        params?.height = height
        params?.gravity = gravity
        window?.attributes = params
        if (style != 0) {
            window?.attributes?.windowAnimations = style
        }
        dialog.apply(mDialog)
        return dialog
    }
}



/**设置view显示（VISIBLE）或隐藏(GONE)*/
fun View?.setVisible(visible: Boolean) {
    this?.apply {
        visibility = if (visible) View.VISIBLE else View.GONE
    }
}

/**一个无限旋转的动画*/
fun View?.startInfiniteRotation() {
    this?.apply {
        val rotationAnim = ObjectAnimator.ofFloat(this, "rotation", 360f)
        rotationAnim?.duration = 1000
        rotationAnim?.repeatCount = ValueAnimator.INFINITE//无限循环
        rotationAnim?.repeatMode = ValueAnimator.RESTART
        rotationAnim?.start()
    }
}

fun Float.dp(): Float {
    return TypedValue.applyDimension(
            TypedValue.COMPLEX_UNIT_DIP,
            this,
            Resources.getSystem().displayMetrics
    )
}




fun Float.sp(): Float {
    return TypedValue.applyDimension(
            TypedValue.COMPLEX_UNIT_SP,
            this,
            Resources.getSystem().displayMetrics
    )
}

fun Float.mm2(): Float {
    return TypedValue.applyDimension(
        TypedValue.COMPLEX_UNIT_MM,
        this,
        Resources.getSystem().displayMetrics
    )
}

fun String.color() = Color.parseColor(this)


fun EditText?.Text(): String {
    return this?.text?.toString()?.trim() ?: ""
}
fun <T>Intent.getParcelableExtraData(name:String, clazz: Class<T> ): T?{
    return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
        getParcelableExtra(name, clazz)
    }else{
        getParcelableExtra(name)
    }
}

/**小数位处理*/
fun String.setScale(newScale: Int = 4, roundingMode: Int = BigDecimal.ROUND_DOWN): String {
    return if (this.isPureNumberOrDecimal()) {
        BigDecimal(this).setScale(newScale, roundingMode)
                .toPlainString()              //如此，一句话就可以了？？
    } else {
        this
    }
}

fun Double?.toPlainString(): String? {
    return this?.toBigDecimal()?.toPlainString()
}

/**小数位处理*/
fun String.setScaleRemoveZero(
        newScale: Int = 4,
        roundingMode: Int = BigDecimal.ROUND_DOWN
): String {
    return this.setScale(newScale, roundingMode).removeExtraZero()
}


/** double 小数位处理*/
fun Double.setScale(newScale: Int = 4, roundingMode: Int = BigDecimal.ROUND_DOWN): String {
    return BigDecimal.valueOf(this).setScale(newScale, roundingMode).toPlainString()
}

/**
 * double 小数位处理 且去除多余的0
 */
fun Double.setScaleRemoveZero(
        newScale: Int = 4,
        roundingMode: Int = BigDecimal.ROUND_DOWN
): String {
    return this.setScale(newScale, roundingMode).removeExtraZero()
}


/**
 * String 数值加法
 **/
infix fun String.add(a: String): String {
    if (this.isNullOrBlank() || a.isNullOrBlank())
        return "0".setScale()
    if (this.startsWith(".") || a.startsWith("."))
        return "0".setScale()
    if (this.isPureNumberOrDecimal() && a.isPureNumberOrDecimal()) {
        return BigDecimal(this).add(BigDecimal(a)).toPlainString().setScale()
    } else {
        var start = if (this.endsWith(".")) this.split(".")[0] else this
        var end = if (a.endsWith(".")) a.split(".")[0] else a
//        Timber.e("You can only use a Number invoke this function")
        return if (this.endsWith(".") || a.endsWith(".")) BigDecimal(start).add(BigDecimal(end))
                .toPlainString().setScale() else ""
    }
}

infix fun Double.add(a: Double): String {
    return BigDecimal.valueOf(this).add(BigDecimal.valueOf(a)).toPlainString()
}

/**
 * String 数值减法
 **/
infix fun String.sub(a: String): String {
    if (this.isNullOrBlank() || a.isNullOrBlank())
        return "0".setScale()
    if (this.startsWith(".") || a.startsWith("."))
        return "0".setScale()
    if (this.isPureNumberOrDecimal() && a.isPureNumberOrDecimal()) {
        return BigDecimal(this).subtract(BigDecimal(a)).toPlainString().setScale()
    } else {
        var start = if (this.endsWith(".")) this.split(".")[0] else this
        var end = if (a.endsWith(".")) a.split(".")[0] else a
//        Timber.e("You can only use a Number invoke this function")
        return if (this.endsWith(".") || a.endsWith(".")) BigDecimal(start).subtract(BigDecimal(end))
                .toPlainString().setScale() else ""
    }
}

infix fun Double.sub(a: Double): String {
    return BigDecimal.valueOf(this).subtract(BigDecimal.valueOf(a)).toPlainString()
}


/**
 * String 数值乘法
 **/
infix fun String?.mul(a: String): String {
    if (this.isNullOrBlank() || a.isNullOrBlank())
        return "0".setScale()
    if (this.startsWith(".") || a.startsWith("."))
        return "0".setScale()
    if (this.isPureNumberOrDecimal() && a.isPureNumberOrDecimal()) {
        return BigDecimal(this).multiply(BigDecimal(a)).toPlainString().setScale()
    } else {
        var start = if (this.endsWith(".")) this.split(".")[0] else this
        var end = if (a.endsWith(".")) a.split(".")[0] else a
//        Timber.e("You can only use a Number invoke this function")
        return if (this.endsWith(".") || a.endsWith(".")) BigDecimal(start).multiply(BigDecimal(end))
                .toPlainString().setScale() else ""
    }
}

infix fun Double.mul(a: Double): String {
    return BigDecimal.valueOf(this).multiply(BigDecimal.valueOf(a)).toPlainString()
}

/**
 * String 数值除法
 **/
infix fun String.div(a: String): String {
    if (this.isNullOrBlank() || a.isNullOrBlank())
        return "0".setScale()
    if (BigDecimal(a).compareTo(BigDecimal.ZERO) == 0)
        return "0".setScale()
    if (this.startsWith(".") || a.startsWith("."))
        return "0".setScale()
    if (this.isPureNumberOrDecimal() && a.isPureNumberOrDecimal()) {
        return BigDecimal(this).divide(BigDecimal(a), 4, BigDecimal.ROUND_HALF_UP).toPlainString()
                .setScale()
    } else {
        var start = if (this.endsWith(".")) this.split(".")[0] else this
        var end = if (a.endsWith(".")) a.split(".")[0] else a
//        Timber.e("You can only use a Number invoke this function")
        return if (this.endsWith(".") || a.endsWith(".")) BigDecimal(start).divide(
                BigDecimal(end),
                4,
                BigDecimal.ROUND_HALF_UP
        ).toPlainString().setScale() else ""
    }
}

infix fun Double.div(a: Double): String {
    if (a == 0.0) {
        return "0"
    }
    return BigDecimal.valueOf(this).divide(BigDecimal.valueOf(a)).toPlainString()
}


/**去掉小数点后多余的零*/
fun String.removeExtraZero(): String {
    var result_str = this
    if (result_str.indexOf(".") > 0) {
        result_str = Pattern.compile("0+?$").matcher(result_str).replaceAll("").trim()//去掉多余的0
        result_str = Pattern.compile("[.]$").matcher(result_str).replaceAll("").trim()//如最后一位是.则去掉
    }
    return result_str
}

/**判断一个字符串，是否是数字。*/
fun String.isPureNumberOrDecimal(): Boolean {

    val reNum = "^[-]?[0-9]+(.[0-9]+)?$".toRegex()//判断是否是数字。
    val regScience = "^((-?\\d+.?\\d*)[Ee]{1}(-?\\d+))$".toRegex()//判断

    return this.matches(reNum) || this.matches(regScience)
}



fun Any.runOnMainThread(your_Action: () -> Unit) {
    Handler(Looper.getMainLooper()).post {
        your_Action.invoke()
    }
}

/**复制到剪切板*/
fun String.copyToClipboard(activity: Activity) {
    runOnMainThread {
        val cm = activity.getSystemService(Context.CLIPBOARD_SERVICE) as (ClipboardManager)
        val clipData = ClipData.newPlainText("Label", this) as ClipData
        cm.setPrimaryClip(clipData)
        toast("复制成功")
    }
}



/**获取view截图*/
fun View.coverViewToBitmap(useMeasureSize: Boolean = true): Bitmap? {
    try {
        val returnedBitmap = if (useMeasureSize) {
            val dm = context.resources.displayMetrics
            measure(
                    View.MeasureSpec.makeMeasureSpec(dm.widthPixels, View.MeasureSpec.EXACTLY),
                    View.MeasureSpec.makeMeasureSpec(dm.heightPixels, View.MeasureSpec.EXACTLY)
            )
            layout(0, 0, measuredWidth, measuredHeight)
            Bitmap.createBitmap(
                    measuredWidth, measuredHeight, Bitmap.Config.ARGB_8888
            )
        } else {
            Bitmap.createBitmap(
                    width, height, Bitmap.Config.ARGB_8888
            )
        }
        val canvas = Canvas(returnedBitmap);
        draw(canvas);
        return returnedBitmap
    } catch (e: Exception) {
        return null
    }
}


/**设置text*/
fun TextView?.setTx(str: String?) {
    str?.let {
        if (str != "null") {
            this?.text = it
        }
    }
}

/**设置text*/
fun TextView?.setTx(@StringRes strRes: Int) {
    this?.text = this?.context?.getString(strRes)
}

/**获取文件后缀名*/
fun String.getFileExtraName(): String? {
    val pointIndex = lastIndexOf(".")
    return if (pointIndex == -1) {
        null
    } else {
        substring(pointIndex + 1, length)
    }
}

/**获取屏幕的宽*/
fun Context.getScreenWidth(): Int {
    val wm = getSystemService(Context.WINDOW_SERVICE) as WindowManager
    val dm = DisplayMetrics()
    wm.defaultDisplay.getMetrics(dm)
    return dm.widthPixels
}

/**获取屏幕的高度*/
fun Context.getScreenHeight(): Int {
    val wm = getSystemService(Context.WINDOW_SERVICE) as WindowManager
    val dm = DisplayMetrics()
    wm.defaultDisplay.getMetrics(dm)
    return dm.heightPixels
}

fun Context.hideKeyboard(token: IBinder?): Boolean {
    if (token != null) {
        val im = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
        return im.hideSoftInputFromWindow(token, InputMethodManager.HIDE_NOT_ALWAYS)
    }
    return false
}
fun View.setCornerRadius(radius: Float) {
    clipToOutline = true
    outlineProvider = object : ViewOutlineProvider() {
        override fun getOutline(view: View, outline: Outline) {
            outline.setRoundRect(0, 0, view.width, view.height, radius)
        }
    }
}

fun RecyclerView.scrollToCenter(position: Int) {
    val layoutManager = this.layoutManager as? LinearLayoutManager ?: return

    val scroller = object : LinearSmoothScroller(this.context) {
        override fun getVerticalSnapPreference(): Int = SNAP_TO_START
        override fun getHorizontalSnapPreference(): Int = SNAP_TO_START

        override fun calculateDyToMakeVisible(view: View, snapPreference: Int): Int {
            val layoutManager = layoutManager ?: return 0
            val parentCenter = height / 2
            val childCenter = (view.top + view.bottom) / 2
            return childCenter - parentCenter
        }

        override fun calculateDxToMakeVisible(view: View, snapPreference: Int): Int {
            val layoutManager = layoutManager ?: return 0
            val parentCenter = width / 2
            val childCenter = (view.left + view.right) / 2
            return childCenter - parentCenter
        }
    }

    scroller.targetPosition = position
    layoutManager.startSmoothScroll(scroller)
}






